package customerSelection;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;

import entities.Customer;
import entities.Product;
import entities.Rule;
import fileProcessing.CorrelationFinding;
import fileProcessing.ParseFiles;

public class Main 
{
	/*command line arguments -
	 * rules file
	 * products file (the top products for which customers are to be selected)
	 * baskets file
	 * number of customers to be selected for each product
	 * Improvement for Value1 on/off (1/0) (default 0) - Dividing by number of items on the left hand side of the rule
	 * Improvement for Value1 on/off (1/0) (default 0) - Dividing by the number of transactions for that customer
	 * Improvement for selecting added value for a customer - if 1 (default) -> use the paper method i.e. consider added effect initially and then the additional value
	 * 														- if 0 -> use the other method where customer are re ranked based on the difference in the inclusive value due to adding the new product
	 * Improvement based on purchase history - Considering the purchase history based monthly weight sum  in value1 calculation    
	*/
	public static void main(String[] args)
	{
		if(args.length < 4)
			System.out.println("File names missing");
		else
		{
			CustomerSelection.rules = new ArrayList<Rule>(ParseFiles.ParseRuleFile(args[0]));
			CustomerSelection.products = new HashMap<Integer, Product>(ParseFiles.ParseProductFile(args[1]));
			CustomerSelection.customers = new HashMap<Integer, Customer>(ParseFiles.ParseTransactionsFile(args[2]));
			
			CustomerSelection.N = Integer.parseInt(args[3]);
			
			//associate products with the set of rules having the product as the antecedent
			Product.findRulesWithProductAsAntecedent(CustomerSelection.rules, CustomerSelection.products);
			
			int divideByNLHS = 0;
			int divideByNTotal = 0;
			int usePurchaseHistory = 0;
			boolean usePaperMethod = true;
			if(args.length >= 8)
			{
				divideByNLHS = Integer.parseInt(args[4]);
				divideByNTotal = Integer.parseInt(args[5]);
				if(Integer.parseInt(args[6]) == 0)
					usePaperMethod = false;
				usePurchaseHistory = Integer.parseInt(args[7]);
			}
			
			//run the customer selection algorithm
			TreeMap<Product, ArrayList<Customer>> selectedCustomers = CustomerSelection.SelectCustomers(divideByNLHS, divideByNTotal, usePaperMethod, usePurchaseHistory);
			
			System.out.println("******************************************************");
			
			//create the string to print
			StringBuilder outputSb = new StringBuilder();
			
			//array list to store the customers
			ArrayList<Integer> allSelectedCustomers = new ArrayList<Integer>();
			
			//customers for each product
			outputSb.append("Selected customers - Top ");
			outputSb.append(CustomerSelection.N);
			outputSb.append(" customers for each product");
			outputSb.append(System.getProperty("line.separator"));
			Iterator<Product> iteratorProducts = selectedCustomers.keySet().iterator();			
			Iterator<ArrayList<Customer>> iteratorCustomers = selectedCustomers.values().iterator();
			while(iteratorProducts.hasNext())
			{
				Product product = iteratorProducts.next();
				ArrayList<Customer> customers = iteratorCustomers.next();
				
				outputSb.append("Product: ");
				outputSb.append(product.getProductId());
				outputSb.append(", Customers:");
				for (Customer customer : customers) 
				{
					outputSb.append(" ");
					outputSb.append(customer.getCustomerId());
					outputSb.append("(");
					outputSb.append(customer.getSelectedForProductsValue1(product.getProductId()));
					outputSb.append(")");
					outputSb.append(",");	
					
					//adding customer to the list storing all selected customers
					if(!allSelectedCustomers.contains(customer.getCustomerId()))
						allSelectedCustomers.add(customer.getCustomerId());					
				}
				outputSb.append(System.getProperty("line.separator"));
			}
			
			//total inclusive value of the selection
			double totalInclusiveValue = 0;
			double totalCorrelationValue = 0;
			double averageNumberOfProductsPerCustomer = 0;
			
			//number of times each customer is selected
			outputSb.append(System.getProperty("line.separator"));
			outputSb.append("******************************************************");
			outputSb.append(System.getProperty("line.separator"));
			outputSb.append("Number of unique customers - ");
			outputSb.append(allSelectedCustomers.size());
			outputSb.append(System.getProperty("line.separator"));
			outputSb.append("Number of times each customer is selected");
			outputSb.append(System.getProperty("line.separator"));
			for(int i = 0; i < allSelectedCustomers.size(); i++)
			{
				outputSb.append(" ");
				int customerId = allSelectedCustomers.get(i);
				outputSb.append(customerId);						
				Customer c = CustomerSelection.customers.get(customerId);
				
				//number of products for which this customer is selected
				int nrProducts = c.getNrProductsForWhichSelected();				
				outputSb.append("; Number of products - ");
				outputSb.append(nrProducts);
				averageNumberOfProductsPerCustomer += nrProducts;
				
				//all three are 1 so that we get a common inclusive value calculation function for all cases
				double inclusiveValue = c.calculateInclusiveValue(1, 1, 1);
				outputSb.append("; Inclusive value - ");
				outputSb.append(inclusiveValue);
				
				//update total inclusive value
				totalInclusiveValue += inclusiveValue;
				
				double correlation = CorrelationFinding.findCorrelation(c);
				outputSb.append("; Correlation value - ");
				outputSb.append(correlation);
				outputSb.append(System.getProperty("line.separator"));
				
				//update total correlation value
				totalCorrelationValue += correlation;
			}			
			
			outputSb.append(System.getProperty("line.separator"));
			outputSb.append("******************************************************");
			
			outputSb.append(System.getProperty("line.separator"));
			outputSb.append("Average number of products selected per customer - ");
			outputSb.append(averageNumberOfProductsPerCustomer/allSelectedCustomers.size());
			
			outputSb.append(System.getProperty("line.separator"));
			outputSb.append("Total Inclusive Value - ");
			outputSb.append(totalInclusiveValue);
			
			outputSb.append(System.getProperty("line.separator"));
			outputSb.append("Total Correlation Value - ");
			outputSb.append(totalCorrelationValue);
			
			//print to the console
			System.out.println(outputSb.toString());
			
			//write to file
	    	try 
			{
				FileWriter file = new FileWriter("selectedCustomers", true);
				file.write(outputSb.toString());
				file.close();
			} 
			catch (IOException e) 
			{
				e.printStackTrace();
			}
		}
	}

}
